home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / bit / src / forms / FORMS / browser.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  19KB  |  608 lines

  1. /*
  2.  * browser.c
  3.  *
  4.  * Forms Object class: BROWSER
  5.  *
  6.  * Written by: Mark Overmars
  7.  *
  8.  * Version 2.2 a
  9.  * Date: Jan 25, 1993
  10.  */
  11.  
  12. #include <malloc.h>
  13. #include <string.h>
  14. #include <stdio.h>
  15. #include <sys/types.h>
  16. #include "forms.h"
  17.  
  18. #define NL    10
  19.  
  20. /* Object specific information */
  21.  
  22. typedef struct {
  23.   int selected;            /* Whether selected */
  24.   char txt[FL_BROWSER_LINELENGTH];    /* The text */
  25. } LINE;
  26.  
  27. typedef struct {
  28.   LINE *text[FL_BROWSER_MAXLINE+1];/* The lines of text (line 0 is not used) */
  29.   int topline;                    /* Current topline */
  30.   int lines;                      /* Number of lines */
  31.   int selectline;        /* Last selected line */
  32.   float fontsize;                 /* The character size */
  33.   int fontstyle;        /* Style of font */
  34.   char specialkey;        /* Key that indicates a special symbol */
  35. } SPEC;
  36.  
  37.  
  38. /***************** DATA STRUCTURE MAINTENANCE ************************/
  39.  
  40. static void delete_line(FL_OBJECT *ob, int linenumb)
  41. /* Deletes a line from the browser */
  42. {
  43.   SPEC *sp = ((SPEC *)(ob->spec));
  44.   LINE *ttt;
  45.   int i;
  46.   ttt = sp->text[linenumb];
  47.   for (i=linenumb; i<sp->lines; i++) sp->text[i] = sp->text[i+1];
  48.   sp->text[sp->lines] = ttt;
  49.   sp->lines--;
  50.   if (sp->selectline == linenumb) sp->selectline = 0;
  51.   else if (sp->selectline > linenumb) sp->selectline--;
  52. }
  53.  
  54. static void insert_line(FL_OBJECT *ob, int linenumb, const char *newtext)
  55. /* Inserts a line of text to a browser */
  56. {
  57.   SPEC *sp = ((SPEC *)(ob->spec));
  58.   LINE *ttt;
  59.   int i;
  60.   if (sp->lines == FL_BROWSER_MAXLINE) 
  61.   {
  62.     delete_line(ob,0);
  63.     linenumb--;
  64.   }
  65.   sp->lines++;
  66.   /* Create new line if required */
  67.   if (sp->text[sp->lines] == NULL) 
  68.     sp->text[sp->lines] = (LINE *) fl_malloc(sizeof(LINE));
  69.   /* Shift lines */
  70.   ttt = sp->text[sp->lines];
  71.   for (i=sp->lines-1; i>=linenumb; i--) sp->text[i+1] = sp->text[i];
  72.   sp->text[linenumb] = ttt;
  73.   /* Fill in line */
  74.   sp->text[linenumb]->selected = 0;
  75.   strncpy(sp->text[linenumb]->txt,newtext,FL_BROWSER_LINELENGTH);
  76.   sp->text[linenumb]->txt[FL_BROWSER_LINELENGTH-1] = NULL;
  77.   if (sp->selectline >= linenumb) sp->selectline++;
  78. }
  79.  
  80. static void replace_line(FL_OBJECT *ob, int linenumb, const char *newtext)
  81. /* Replaces a line of text in a browser */
  82. {
  83.   SPEC *sp = ((SPEC *)(ob->spec));
  84.   /* Fill in line */
  85.   strncpy(sp->text[linenumb]->txt,newtext,FL_BROWSER_LINELENGTH);
  86.   sp->text[linenumb]->txt[FL_BROWSER_LINELENGTH-1] = NULL;
  87. }
  88.  
  89. /******************************** DRAWING ********************************/
  90.  
  91. static int partial = 0;        /* Whether the next redraw should be partial.*/
  92.                 /* 0 = not, 1 = no back, 2 = no back, slider.*/
  93.  
  94. static void calc_textarea(FL_OBJECT *ob, float *xx, float *yy,
  95.                 float *ww, float *hh, int *screenlines)
  96. /* Calculates the area in which the text is drawn */
  97. {
  98.   SPEC *sp = ((SPEC *)(ob->spec));
  99.   float charheight = fl_get_char_height(sp->fontsize, sp->fontstyle);
  100.                          /* character height */
  101.   *xx = ob->x + 1.5*FL_BROWSER_BW;
  102.   *yy = ob->y + 1.0*FL_BROWSER_BW;
  103.   *ww = ob->w - 3.0*FL_BROWSER_BW;
  104.   *hh = ob->h - 2.0*FL_BROWSER_BW;
  105.   *screenlines = (int) (*hh / charheight);
  106.   /* Check whether a slider will be shown */
  107.   if (sp->lines > *screenlines)
  108.     { *xx += 7.0*FL_BROWSER_BW; *ww -= 7.0*FL_BROWSER_BW;}
  109. }
  110.  
  111. static void correct_topline(FL_OBJECT *ob)
  112. /* Corrects the position of the topline inside the browser */
  113. {
  114.   SPEC *sp = ((SPEC *)(ob->spec));
  115.   int screenlines;                              /* lines on screen */
  116.   float xx,yy,ww,hh;                /* text box */
  117.   calc_textarea(ob,&xx,&yy,&ww,&hh,&screenlines);
  118.   if (sp->lines > screenlines)
  119.   {
  120.     if (sp->lines - sp->topline + 1 < screenlines)
  121.       sp->topline = sp->lines - screenlines + 1;
  122.     if (sp->topline < 1) sp->topline = 1;
  123.   }
  124.   else
  125.     sp->topline = 1;
  126. }
  127.  
  128. static void draw_textline(FL_OBJECT *ob, int line, float xx, float yy, float ww,
  129.                 int back)
  130. /* Draws the line on the browser at postion xx,yy, with maximal width ww.
  131.    back indicates whether the background should be drawn */
  132. {
  133.   SPEC *sp = ((SPEC *)(ob->spec));
  134.   char *str;                /* Start of actual string */
  135.   int style = sp->fontstyle;        /* Actual font style used */
  136.   float size = sp->fontsize;        /* Actual font size used */
  137.   int lcol = ob->lcol;            /* Actual font color used */
  138.   int align = FL_ALIGN_LEFT;        /* Actual alignment used */
  139.   float charheight = fl_get_char_height(size, style);
  140.  
  141.   /* Draw the selection box if required */
  142.   if (line <= sp->lines && sp->text[line]->selected)
  143.     fl_rect(xx,yy-0.6*charheight,ww,charheight,ob->col2);
  144.   else if (back)
  145.     fl_rect(xx,yy-0.6*charheight,ww,charheight,ob->col1);
  146.   if (line > sp->lines) return;
  147.  
  148.   /* Check for special lines */
  149.   str = sp->text[line]->txt;
  150.   while (str[0] != '\0' && str[0] == sp->specialkey)
  151.   {
  152.     switch (str[1]) {
  153.       case 'l': size = FL_LARGE_FONT;yy -= 5.0; break;
  154.       case 's': size = FL_SMALL_FONT; break;
  155.       case 'b':    style = FL_BOLD_STYLE; break;
  156.       case 'i':    style = FL_ITALIC_STYLE; break;
  157.       case 'f':    style = FL_FIXED_STYLE; break;
  158.       case 'c':    align = FL_ALIGN_CENTER; break;
  159.       case 'r':    align = FL_ALIGN_RIGHT; break;
  160.       case 'C':
  161.         lcol = 0;
  162.         while (str[2] >= '0' && str[2] <= '9')
  163.           {lcol = 10* lcol + str[2] - '0'; str++;}
  164.     break;
  165.       case '_':    /* line under it */
  166.     fl_line(xx,yy-0.6*charheight,ww,1.0,BLACK);
  167.     break;
  168.     }
  169.     str++; str++;
  170.   }
  171.   /* Draw the string */
  172.   fl_drw_text_cursor(align,xx,yy,ww,0.0,lcol,size,style,str,0,-1);
  173. }
  174.  
  175. static void draw_browslider(FL_OBJECT *ob, int screenlines)
  176. /* Draws the slider if required. */
  177. {
  178.   SPEC *sp = ((SPEC *)(ob->spec));
  179.   float slsize, slpos;                          /* slider size and position */
  180.   slsize = (1.0*screenlines) / sp->lines;
  181.   slpos = 1.0 - (1.0*sp->topline -1.0) / (sp->lines - screenlines);
  182.   fl_drw_slider(ob->boxtype, ob->x,ob->y,7.0*FL_BROWSER_BW,ob->h,
  183.         FL_BROWSER_SLCOL,FL_BROWSER_SLCOL,FL_VERT_SLIDER,
  184.         slsize,slpos,"");
  185. }
  186.  
  187. static void draw_browser(FL_OBJECT *ob)
  188. /* Draws the browser */
  189. {
  190.   SPEC *sp = ((SPEC *)(ob->spec));
  191.   float charheight = fl_get_char_height(sp->fontsize, sp->fontstyle);
  192.                         /* character height */
  193.   int screenlines;                              /* lines on screen */
  194.   int i;                                     /* counters, etc. */
  195.   float xx,yy,ww,hh;                /* text box */
  196.   calc_textarea(ob,&xx,&yy,&ww,&hh,&screenlines);
  197.   correct_topline(ob);
  198.   if (sp->lines > screenlines)
  199.   {
  200.     draw_browslider(ob,screenlines);
  201.     fl_drw_box(ob->boxtype,ob->x+7.0*FL_BROWSER_BW,ob->y,
  202.         ob->w-7.0*FL_BROWSER_BW,ob->h, ob->col1,FL_BROWSER_BW);
  203.   }
  204.   else
  205.   {
  206.     fl_drw_box(ob->boxtype,ob->x,ob->y,ob->w,ob->h,ob->col1,FL_BROWSER_BW);
  207.   }
  208.   fl_drw_text_beside(ob->align,ob->x,ob->y,ob->w,ob->h,
  209.         ob->lcol,ob->lsize,ob->lstyle,ob->label);
  210.   fl_set_clipping(xx,yy,ww,hh-1.0);
  211.   for (i=screenlines-1; i >= 0 ; i--)
  212.     draw_textline(ob,i+sp->topline,xx,yy+hh-(i+0.5)*charheight,ww,FALSE);
  213.   fl_unset_clipping();
  214. }
  215.  
  216. static void draw_browser_partial(FL_OBJECT *ob, int slid)
  217. /* Draws the contents of the browser only. slid indicated whether the
  218.    slider should be redrawn. */
  219. {
  220.   SPEC *sp = ((SPEC *)(ob->spec));
  221.   float charheight;                /* character height */
  222.   int screenlines;                              /* lines on screen */
  223.   int i;                                     /* counters, etc. */
  224.   float xx,yy,ww,hh;                /* text box */
  225.   charheight = fl_get_char_height(sp->fontsize, sp->fontstyle);
  226.   calc_textarea(ob,&xx,&yy,&ww,&hh,&screenlines);
  227.   correct_topline(ob);
  228.   if (slid && sp->lines > screenlines) draw_browslider(ob,screenlines);
  229.   fl_set_clipping(xx,yy,ww,hh-1.);
  230.   for (i=screenlines-1; i >= 0 ; i--)
  231.     draw_textline(ob,i+sp->topline,xx,yy+hh-(i+0.5)*charheight,ww,TRUE);
  232.   fl_unset_clipping();
  233. }
  234.  
  235. /***************** HANDLING EVENTS **************************/
  236.  
  237. #define NOEVENT        0
  238. #define SELECTEVENT    1
  239. #define DESELECTEVENT    2
  240. #define SLIDEREVENT    3
  241. #define PAGEEVENT    4
  242.  
  243. static int eventtype = NOEVENT;    /* Type of interaction taking place */
  244. static int pagesize;        /* Amount to scroll for page events */
  245.  
  246. static int timdel;        /* Time passes since last page change */
  247.  
  248. static int handle_mouse(FL_OBJECT *ob, float mx, float my)
  249. /* handles a mouse change. returns whether a selection change has occured */
  250. {
  251.   SPEC *sp = ((SPEC *)(ob->spec));
  252.   float charheight = fl_get_char_height(sp->fontsize, sp->fontstyle);
  253.                         /* character height */
  254.   int screenlines;                              /* lines on screen */
  255.   float slsize,slpos,slval;                     /* slider size,pos and value */
  256.   int line;                                     /* new number of lines */
  257.   int oldtopline = sp->topline;            /* old value of topline */
  258.   int newtopline;                /* New topline */
  259.   int slaction;                    /* Type of slider action */
  260.  
  261.   /* Check whether ther are any lines */
  262.   if (sp->lines == 0) return FALSE;
  263.   
  264.   /* Compute possible slider position change */
  265.   correct_topline(ob);
  266.   screenlines = (int) ((ob->h - 2.0*FL_BROWSER_BW) / charheight);
  267.   if (sp->lines > screenlines)
  268.   {
  269.     slsize = (1.0*screenlines) / sp->lines;
  270.     slpos = 1.0 - (1.0*sp->topline -1.0) / (sp->lines - screenlines);
  271.     slaction = fl_get_pos_in_slider(ob->x,ob->y,ob->w,ob->h,
  272.             FL_VERT_SLIDER,slsize,mx,my, slpos,&slval);
  273.     newtopline = (int) ((1.0-slval)*(sp->lines - screenlines) + 1.0);
  274.   }
  275.  
  276.   /* Determine the type of event */
  277.   if (eventtype == NOEVENT)
  278.   {
  279.     if (sp->lines > screenlines && mx < ob->x+7.0*FL_BROWSER_BW)
  280.     {
  281.       if (slaction == 0)
  282.         eventtype = SLIDEREVENT;
  283.       else
  284.       {
  285.         eventtype =PAGEEVENT;
  286.         timdel = 0;
  287.         if (slaction == -2)      pagesize = screenlines;
  288.         else if (slaction == -1) pagesize = 1;
  289.         else if (slaction == 1)  pagesize = -1;
  290.         else if (slaction == 2)  pagesize = -screenlines;
  291.       }
  292.     }
  293.     else
  294.     {
  295.       eventtype = SELECTEVENT;
  296.       line = sp->topline - (int) ((my-(ob->y+ob->h-FL_BROWSER_BW))/charheight);
  297.       if (ob->type == FL_MULTI_BROWSER &&
  298.           line >= 1 && line <= sp->lines && line < sp->topline+screenlines &&
  299.           sp->text[line]->selected)
  300.         eventtype = DESELECTEVENT;
  301.     }
  302.   }
  303.  
  304.   /* Handle the event */
  305.   switch (eventtype) {
  306.     case PAGEEVENT:
  307.         if ((timdel++ % 30) == 0)
  308.         {
  309.           sp->topline += pagesize;
  310.           correct_topline(ob);
  311.           if (sp->topline == oldtopline) return 0;
  312.           partial = 1; fl_redraw_object(ob);
  313.         }
  314.         return 0;
  315.     case SLIDEREVENT:
  316.     sp->topline = newtopline;
  317.         correct_topline(ob);
  318.     if (sp->topline == oldtopline) return 0;
  319.     partial = 1; fl_redraw_object(ob);
  320.     return 0;
  321.     default:
  322.     if (ob->type == FL_NORMAL_BROWSER) return 0;
  323.     line = sp->topline - (int)((my-(ob->y+ob->h-FL_BROWSER_BW))/charheight);
  324.     if (line<sp->topline) line = sp->topline;
  325.      if (line>=sp->topline+screenlines) line = sp->topline+screenlines-1;
  326.      if (line>sp->lines) line = sp->lines;
  327.     if (eventtype == SELECTEVENT)
  328.     {
  329.       if (sp->text[line]->selected) return (ob->type != FL_MULTI_BROWSER);
  330.       if (ob->type != FL_MULTI_BROWSER && sp->selectline > 0) 
  331.         sp->text[sp->selectline]->selected = 0;
  332.       sp->text[line]->selected = 1;
  333.       sp->selectline = line;
  334.     }
  335.     else /* eventtype == DESELECTEVENT && ob->type == FL_MULTI_BROWSER */
  336.     {
  337.       if (! sp->text[line]->selected) return 0;
  338.       sp->text[line]->selected = 0;
  339.       sp->selectline = -line;
  340.     }
  341.     partial = 2; fl_redraw_object(ob);
  342.     return 1;
  343.   }
  344. }
  345.  
  346. /*-----------------------------------------------*/
  347.  
  348. static int statuschanged = 0;
  349.  
  350. static int handle_browser(FL_OBJECT *ob, int event, float mx, float my, char key)
  351. /* Handles the browser */
  352. {
  353.   int i;
  354.   SPEC *sp = ((SPEC *)(ob->spec));
  355.   switch (event)
  356.   {
  357.     case FL_DRAW:
  358.         if (partial == 0 || ob->form->doublebuf) draw_browser(ob);
  359.         else if (partial == 1) draw_browser_partial(ob,TRUE);
  360.         else if (partial == 2) draw_browser_partial(ob,FALSE);
  361.         partial = 0;
  362.         return 0;
  363.     case FL_PUSH:
  364.     eventtype = NOEVENT;
  365.         statuschanged = 0;
  366.     case FL_MOUSE:
  367.     if (eventtype == SELECTEVENT || eventtype == DESELECTEVENT)
  368.     {
  369.       if (my < ob->y) fl_set_browser_topline(ob,sp->topline+1);
  370.       else if (my > ob->y+ob->h) fl_set_browser_topline(ob,sp->topline-1);
  371.         }
  372.         if (handle_mouse(ob,mx,my)) statuschanged = 1;
  373.         if (statuschanged && ob->type == FL_MULTI_BROWSER)
  374.       { statuschanged = 0; return 1; }
  375.     return 0;
  376.     case FL_RELEASE:
  377.         if (ob->type == FL_SELECT_BROWSER) fl_deselect_browser(ob);
  378.     return statuschanged;
  379.     case FL_FREEMEM:
  380.     for (i=1; i<=FL_BROWSER_MAXLINE; i++)
  381.         if (sp->text[i] != NULL) free(sp->text[i]);
  382.     free(ob->spec);
  383.     return 0;
  384.   }
  385.   return 0;
  386. }
  387.  
  388. /*-----------------------------------------------*/
  389.  
  390. FL_OBJECT *fl_create_browser(int type,float x,float y,float w,float h,
  391. const char *label)
  392. /* Creates a browser */
  393. {
  394.   int i;
  395.   FL_OBJECT *ob;
  396.   SPEC *sp;
  397.   ob = fl_make_object(FL_BROWSER,type,x,y,w,h,label,handle_browser);
  398.   ob->boxtype = FL_BROWSER_BOXTYPE;
  399.   ob->lcol = FL_BROWSER_LCOL;
  400.   ob->align = FL_BROWSER_ALIGN;
  401.   ob->col1 = FL_BROWSER_COL1;
  402.   ob->col2 = FL_BROWSER_COL2;
  403.  
  404.   ob->spec = (int *) fl_malloc(sizeof(SPEC));
  405.   sp = ((SPEC *)(ob->spec));
  406.   sp->fontsize = FL_NORMAL_FONT;
  407.   sp->fontstyle = FL_NORMAL_STYLE;
  408.   sp->lines = 0;
  409.   sp->topline = 1;
  410.   sp->selectline = 0;
  411.   sp->specialkey = '@';
  412.   for (i=0; i <= FL_BROWSER_MAXLINE; i++) sp->text[i] = NULL;
  413.  
  414.   return ob;
  415. }
  416.  
  417. FL_OBJECT *fl_add_browser(int type, float x, float y, float w, float h, 
  418. const char *label)
  419. /* Adds an object */
  420. {
  421.   FL_OBJECT *ob;
  422.   ob = fl_create_browser(type,x,y,w,h,label);
  423.   fl_add_object(fl_current_form,ob);
  424.   return ob;
  425. }
  426.  
  427. /*-----------------------------------------------*/
  428.  
  429. void fl_set_browser_topline(FL_OBJECT *ob, int line)
  430. /* Sets the topline for the browser. */
  431. {
  432.   SPEC *sp = ((SPEC *)(ob->spec));
  433.   if (line<1) line = 1;
  434.   if (line>sp->lines) line = sp->lines;
  435.   if (line == sp->topline) return;
  436.   sp->topline = line;
  437.   fl_redraw_object(ob);
  438. }
  439.  
  440. /*-----------------------------------------------*/
  441.  
  442. void fl_clear_browser(FL_OBJECT *ob)
  443. /* Clears the browser. */
  444. {
  445.   ((SPEC *)(ob->spec))->lines = 0;
  446.   ((SPEC *)(ob->spec))->topline = 1;
  447.   ((SPEC *)(ob->spec))->selectline = 0;
  448.   fl_redraw_object(ob);
  449. }
  450.  
  451. void fl_add_browser_line(FL_OBJECT *ob,const  char *newtext)
  452. /* Adds a line of text to a browser */
  453. {
  454.   insert_line(ob,((SPEC *)(ob->spec))->lines+1,newtext);
  455.   fl_redraw_object(ob);
  456. }
  457.  
  458. void fl_addto_browser(FL_OBJECT *ob, const char *newtext)
  459. /* Adds a line of text to a browser, and changes focus */
  460. {
  461.   insert_line(ob,((SPEC *)(ob->spec))->lines+1,newtext);
  462.   ((SPEC *)(ob->spec))->topline = ((SPEC *)(ob->spec))->lines;
  463.   fl_redraw_object(ob);
  464. }
  465.  
  466. void fl_insert_browser_line(FL_OBJECT *ob, int linenumb, const char *newtext)
  467. /* Inserts a line of text in a browser */
  468. {
  469.   if (linenumb < 1 || linenumb > ((SPEC *)(ob->spec))->lines) return;
  470.   insert_line(ob,linenumb,newtext);
  471.   fl_redraw_object(ob);
  472. }
  473.  
  474. void fl_delete_browser_line(FL_OBJECT *ob, int linenumb)
  475. /* Deletes a line from a browser. */
  476.   if (linenumb < 1 || linenumb > ((SPEC *)(ob->spec))->lines) return;
  477.   delete_line(ob,linenumb);
  478.   fl_redraw_object(ob);
  479. }
  480.  
  481. void fl_replace_browser_line(FL_OBJECT *ob, int linenumb, const char *newtext)
  482. /* Replaces a line of text in a browser */
  483. {
  484.   if (linenumb < 1 || linenumb > ((SPEC *)(ob->spec))->lines) return;
  485.   replace_line(ob,linenumb,newtext);
  486.   fl_redraw_object(ob);
  487. }
  488.  
  489. const char *fl_get_browser_line(FL_OBJECT *ob, int linenumb)
  490. /* Returns a pointer to a particular line in the browser. */
  491. {
  492.   if (linenumb < 1 || linenumb > ((SPEC *)(ob->spec))->lines) return NULL;
  493.   return ((SPEC *)(ob->spec))->text[linenumb]->txt;
  494. }
  495.  
  496. int fl_load_browser(FL_OBJECT *ob, char filename[])
  497. /* Sets the browser to a particular file */
  498. {
  499.   SPEC *sp;
  500.   FILE *fl;
  501.   char newtext[FL_BROWSER_LINELENGTH];
  502.   int c;
  503.   int i;
  504.   if (ob == NULL || ob->objclass != FL_BROWSER) return 0;
  505.   sp = ((SPEC *)(ob->spec));
  506.   fl_clear_browser(ob);
  507.   if (filename == NULL || filename[0] == NULL)
  508.     {fl_redraw_object(ob); return 1;}
  509.   /* LOAD THE FILE */
  510.   fl = fopen(filename,"r");
  511.   if (fl == NULL) return 0;
  512.   i = 0;
  513.   do
  514.   {
  515.     c = getc(fl);
  516.     if (c == NL || c == EOF)
  517.       { newtext[i] = NULL; insert_line(ob,sp->lines+1,newtext); i = 0; }
  518.     else if (c == 9) /* Tab */
  519.       do
  520.     if (i< FL_BROWSER_LINELENGTH-1) newtext[i++] = ' ';
  521.       while ( i % 8 != 0 && i< FL_BROWSER_LINELENGTH-1);
  522.     else if (i< FL_BROWSER_LINELENGTH-1)
  523.       newtext[i++] = c;
  524.   } while (c != EOF);
  525.   fclose(fl);
  526.   fl_redraw_object(ob);
  527.   return 1;
  528. }
  529.  
  530. int fl_get_browser_maxline(FL_OBJECT *ob)
  531. /* Returns the number of lines in the browser. */
  532.   { return ((SPEC *)(ob->spec))->lines; }
  533.  
  534. /*-----------------------------------------------*/
  535.  
  536. void fl_select_browser_line(FL_OBJECT *ob, int line)
  537. /* Selects a line in the browser. */
  538. {
  539.   SPEC *sp = ((SPEC *)(ob->spec));
  540.   if (line < 1 || line > sp->lines) return;
  541.   if (ob->type != FL_MULTI_BROWSER && sp->selectline >0)
  542.     sp->text[sp->selectline]->selected = 0;
  543.   sp->text[line]->selected = 1;
  544.   sp->selectline = line;
  545.   fl_redraw_object(ob);
  546. }
  547.  
  548. void fl_deselect_browser_line(FL_OBJECT *ob, int line)
  549. /* Deselects a line in the browser. */
  550. {
  551.   SPEC *sp = ((SPEC *)(ob->spec));
  552.   if (line < 1 || line > sp->lines) return;
  553.   sp->text[line]->selected = 0;
  554.   if (ob->type != FL_MULTI_BROWSER && sp->selectline == line)
  555.     sp->selectline = 0;
  556.   else if (ob->type == FL_MULTI_BROWSER)
  557.     sp->selectline = -line;
  558.   fl_redraw_object(ob);
  559. }
  560.  
  561. void fl_deselect_browser(FL_OBJECT *ob)
  562. /* Deselects all lines in the browser. */
  563. {
  564.   int i;
  565.   for (i=1; i<= ((SPEC *)(ob->spec))->lines; i++)
  566.     ((SPEC *)(ob->spec))->text[i]->selected = 0;
  567.   fl_redraw_object(ob);
  568. }
  569.  
  570. int fl_isselected_browser_line(FL_OBJECT *ob, int line)
  571. /* Returns whether a line in the browser is selected. */
  572.   if (line < 1 || line > ((SPEC *)(ob->spec))->lines) return 0;
  573.   return ((SPEC *)(ob->spec))->text[line]->selected;
  574. }
  575.  
  576. int fl_get_browser(FL_OBJECT *ob)
  577. /* Returns the last selection in the browser. */
  578.   { return ((SPEC *)(ob->spec))->selectline; }
  579.  
  580. /*-----------------------------------------------*/
  581.  
  582. void fl_set_browser_fontsize(FL_OBJECT *ob, float size)
  583. /* Sets the font size inside the browser. */
  584. {
  585.   ((SPEC *)(ob->spec))->fontsize = size;
  586.   fl_redraw_object(ob);
  587. }
  588. /*TCZ*/
  589. int fl_get_browser_topline(FL_OBJECT *ob)
  590. {
  591.  return ((SPEC *)ob->spec)->topline;
  592. }
  593. void fl_set_browser_fontstyle(FL_OBJECT *ob, int style)
  594. /* Sets the font style inside the browser. */
  595. {
  596.   ((SPEC *)(ob->spec))->fontstyle = style;
  597.   fl_redraw_object(ob);
  598. }
  599.  
  600. void fl_set_browser_specialkey(FL_OBJECT *ob, char specialkey)
  601. /* Sets the escape key used in the text */
  602. {
  603.   ((SPEC *)(ob->spec))->specialkey = specialkey;
  604.   fl_redraw_object(ob);
  605. }
  606.